package libraHystrix;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;

import libra.model.JsonResult;

@RestController
@RequestMapping("provider_hystrix")
// 定义全局默认的fallBack备选方法处理函数
@DefaultProperties( defaultFallback = "defaultFallBack" )
public class ProviderHystrixController {
	
	@Value( "#{'${server.servlet.context-path}'.concat('[port(${server.port})]')}" )
	String identity;
	
	/*
	 * 测试Hystrix正常访问的请求
	 */
	@RequestMapping("ok")
	public Object ok( HttpServletRequest req ) throws Exception{
		System.out.println(identity+"【ok】");
		return new JsonResult<String>(0, identity, "【ok】线程池："+Thread.currentThread().getName());
	}
	
	
	/******************************************/
	/** 以下代码测试provider端的Hystrix服务降级 */
	/******************************************/
	/*
	 * 测试Hystrix异常访问的请求，会导致服务降级
	 */
	@HystrixCommand
	@RequestMapping("errorWithHystrix")
	public Object errorWithHystrix( Boolean flag, HttpServletRequest req ) throws Exception {
		System.out.println(identity+"【errorWithHystrix】");
		int i = 1/( flag?0:1);
		return new JsonResult<String>(0, identity, "正常返回【errorWithHystrix["+i+"]】线程池："+Thread.currentThread().getName());
	}
	// Hystrix服务降级的全局备选方法定义
	public Object defaultFallBack() throws Exception {
		return new JsonResult<String>(0, identity, "全局fallBack【defaultFallBack[全局]】线程池："+Thread.currentThread().getName());
	}
	
	/*
	 * 测试Hystrix超时访问的请求，会导致服务降级
	 */
	@HystrixCommand( fallbackMethod="timeOutFallBack", commandProperties = {
			@HystrixProperty( name="execution.isolation.thread.timeoutInMilliseconds", value="4000"  )
	} )
	@RequestMapping("timeOutWithHystrix")
	public Object timeOutWithHystrix( Boolean flag, HttpServletRequest req ) throws Exception{
		System.out.println(identity+"【timeOutWithHystrix】");
		long sleepTime = flag?3000:5000;
		try {
			Thread.sleep( sleepTime );
		} catch (Exception e) {
		}
		return new JsonResult<String>(0, identity, "正常返回【timeOutWithHystrix["+sleepTime+"]】线程池："+Thread.currentThread().getName());
	}
	// Hystrix服务降级的备选方法定义
	public Object timeOutFallBack( Boolean flag, HttpServletRequest req ) throws Exception{
		return new JsonResult<String>(0, identity, "指定fallBack【timeOutWithHystrixFallBack["+flag+"]】线程池："+Thread.currentThread().getName());
	}
	
	
	
	/*******************************************/
	/** 以下代码测试provider端的Hystrix服务熔断 */
	/******************************************/
	/**
	 * 在规定的时间窗口期内，达到请求次数后，请求失败率达标，断路器工作
	 */
	@HystrixCommand( fallbackMethod = "circuitBreakTestFallBack", commandProperties = {
			@HystrixProperty( name="circuitBreaker.enabled", value="true" ),// 是否开启断路器
			@HystrixProperty( name="circuitBreaker.requestVolumeThreshold", value="10" ),// 请求次数
			@HystrixProperty( name="circuitBreaker.sleepWindowInMilliseconds", value="10000" ),// 时间窗口期
			@HystrixProperty( name="circuitBreaker.errorThresholdPercentage", value="60" ),// 失败率达到多少(百分比)后跳闸
	} )
	@RequestMapping("circuitBreakTest")
	public Object circuitBreakTest( Boolean flag, HttpServletRequest req ) throws Exception {
		if( !flag ) {
			throw new Exception(identity+"circuitBreakTest_Exception");
		}
		return new JsonResult<String>(0, identity, "【circuitBreakTest】线程池："+Thread.currentThread().getName());
	}
	public Object circuitBreakTestFallBack( Boolean flag, HttpServletRequest req ) throws Exception {
		return new JsonResult<String>(0, identity, "【备选circuitBreakTestFallBack["+flag+"]】线程池："+Thread.currentThread().getName());
	}
	
	
	
	/********************************************************/
	/** 以下代码Provider端不处理，用于测试Consumer端的Hystrix */
	/********************************************************/
	@RequestMapping("error")
	public Object error( Boolean flag, HttpServletRequest req ) {
		System.out.println(identity+"【error】");
		int i = 1/( flag?0:1);
		return new JsonResult<String>(0, identity, "【error["+i+"]】线程池："+Thread.currentThread().getName());
	}
	@RequestMapping("timeOut")
	public Object timeOut( Boolean flag, HttpServletRequest req ) throws Exception{
		System.out.println(identity+"【timeOut】");
		long sleepTime = flag?3000:5000;
		try {
			Thread.sleep( sleepTime );
		} catch (Exception e) {
		}
		return new JsonResult<String>(0, identity, "【timeOut["+sleepTime+"]】线程池："+Thread.currentThread().getName());
	}
}
